/*
 * Copyright (c) 2010 Philip Foulkes <philip.foulkes@gmail.com>
 *
 * This file is free software and is made available under the
 * terms of the GNU General Public License, version 2, or at your
 * option, any later version
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/module.h>
#include <linux/slab.h>

#include "../include/mrp_iterator.h"

struct mrp_iterator * mrp_iterator_create_and_init (void * my_object, struct mrp_iterator_ops * mrp_iterator_ops)
{
	struct mrp_iterator * mrp_iterator;

	if (!(mrp_iterator = kzalloc (sizeof(struct mrp_iterator), GFP_KERNEL)))
		return NULL;

	if (mrp_iterator_init (mrp_iterator, my_object, mrp_iterator_ops))
	{
		mrp_iterator_destroy (&mrp_iterator);
		return NULL;
	}

	return mrp_iterator;
}
EXPORT_SYMBOL(mrp_iterator_create_and_init);

int mrp_iterator_init (struct mrp_iterator * mrp_iterator, void * my_object, struct mrp_iterator_ops * mrp_iterator_ops)
{
	if ( 	! mrp_iterator_ops->mrp_iterator_get_internal
		||  ! mrp_iterator_ops->mrp_iterator_next_internal
		||  ! mrp_iterator_ops->mrp_iterator_at_end_internal)
		return -EINVAL;

	mrp_iterator->mrp_iterator_ops = mrp_iterator_ops;
	mrp_iterator->my_object = my_object;
	return 0;
}
EXPORT_SYMBOL(mrp_iterator_init);

void mrp_iterator_destroy (struct mrp_iterator ** mrp_iterator)
{
	struct mrp_iterator * i;

	i = *mrp_iterator;

	if (i)
	{
		mrp_iterator_cleanup (i);
		kfree (i);
		*mrp_iterator = NULL;
	}
}
EXPORT_SYMBOL(mrp_iterator_destroy);

void mrp_iterator_cleanup (struct mrp_iterator * mrp_iterator)
{
	/* nothing for now */
}
EXPORT_SYMBOL(mrp_iterator_cleanup);

void * mrp_iterator_get (struct mrp_iterator * mrp_iterator)
{
	return mrp_iterator->mrp_iterator_ops->mrp_iterator_get_internal (mrp_iterator, mrp_iterator->my_object);
}
EXPORT_SYMBOL(mrp_iterator_get);

void mrp_iterator_next  (struct mrp_iterator * mrp_iterator)
{
	mrp_iterator->mrp_iterator_ops->mrp_iterator_next_internal (mrp_iterator, mrp_iterator->my_object);
}
EXPORT_SYMBOL(mrp_iterator_next);

int mrp_iterator_at_end (struct mrp_iterator * mrp_iterator)
{
	return mrp_iterator->mrp_iterator_ops->mrp_iterator_at_end_internal (mrp_iterator, mrp_iterator->my_object);
}
EXPORT_SYMBOL(mrp_iterator_at_end);
